package com.tang.service;

import com.tang.base.BaseRedis;
import com.tang.constant.Cons;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.support.CorrelationData;

/**
 * 消息发送到交换机确认机制
 * 如果设置了消息持久化，那么ack=true是在消息持久化完成后，就是存到硬盘上之后再发送的，
 * 确保消息已经存在硬盘上，万一消息服务挂了，消息服务恢复是能够再重发消息
 * 消息服务收到消息后，消息会处于"UNACK"的状态，直到客户端确认消息
 * 注意：一旦返回的确认消息丢失，那么那么消息服务会重发消息；如果你设置了autoAck= false，
 * 但又没应答 channel.baskAck也没有应答 channel.baskNack，那么会导致非常严重的错误：
 * 消息队列会被堵塞住，可参考http://blog.sina.com.cn/s/blog_48d4cf2d0102w53t.html 所以，无论如何都必须应答
 */
public class MsgSendConfirmCallBack extends BaseRedis {

    private static final Logger logger = LogManager.getLogger(MsgSendConfirmCallBack.class);

    /**
     * 当消息发送到交换机（exchange）时，该方法被调用.
     * 1.如果消息没有到exchange,则 ack=false
     * 2.如果消息到达exchange,则 ack=true
     *
     * @param correlationData
     * @param ack
     * @param cause
     */
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        logger.info("消息的id（回调id）是>>>>>>>>>>>>>>" + correlationData.getId());
        if (ack) {
            logger.info("消息发送确认成功（消息发送到exchange成功）！");
            // TODO 删除 msgId 与 Message 的关系
            try {
                redisUtil.del(correlationData.getId());
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("缓存错误", e);
            }
        } else {
            logger.info("消息发送确认失败（消息发送到exchange失败）！>>>>>>>>>>>>>" + cause);
            // TODO 消息发送到exchange失败 ，重新发送
            Object cacheKey = null;
            try {
                cacheKey = redisUtil.get(correlationData.getId());
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("缓存错误", e);
            }
            if (null != cacheKey) {
                Message message = (Message) cacheKey;
                // 重新发送消息
                rabbitTemplate.convertAndSend(Cons.TOPIC_EXCHANGE_NAME, Cons.OBJECT_ROUTING_KEY,
                        message, correlationData);

            }
        }
    }
}
